#!/usr/bin/python3
from lib import utils, upload, caches, ssh, logger
from lib.ssh_terminal import SSHTerminal


def show_help():
    print('Hornet Help')
    print('用法：hornet <command> [..options]')
    print('  init            在当前目录初始化配置文件')
    print('  up              上传文件')
    # print('  upgrade         上传之后升级服务器的版本为项目根目录下的.hornet.version.latest文件中的版本号')
    print('  post            单独执行`post_upload`配置的命令')
    print('  clean           清除本项目上传缓存')
    print('  clean-all       清除所有项目上传缓存')
    print('  exec            执行远程命令，如果配置了多个服务器的话需要指定server，只支持Linux环境')
    print('  connect         连接到SSH终端服务，如果配置了多个服务器的话需要指定server，只支持Linux环境')
    print('  server          查看服务器信息`.caches/server-list.json`')
    print('  help            查看帮助')
    print('一次可执行多个操作，例：`hornet clean/up`，先执行`hornet clean`在执行`hornet up`')
    print()
    print('参数选项：')
    print('  -v, --version           上传时指定版本号，文件会上传到对应版本的目录中')
    print('  -U, --only-up           如果配置了`post_upload`，上传完成后不执行`post_upload`配置命令')
    print('  -c, --cmd               执行远程命令时输入的命令，例：hornet exec --cmd "somd command"')
    print('  -s, --server            执行远程命令，连接到SSH终端时需要指定的服务器配置名，对应配置文件中servers.[*].name')
    print('  -uv, --upgrade-version  当没有文件上传时也升级版本号')
    print('  -nv, --not-use-version-file  不使用.hornet.version.latest文件版本')
    print('  -a, --all               全部选项')
    print('  -f, --file              指定配置文件名称')


def get_destination_server(config: dict, args: dict) -> dict:
    """
    获取命令行中指定的服务器信息
    :param config: 配置对象
    :param args: 命令行参数对象
    :return:  server dict info
    """
    servers = utils.get_servers(config)
    slen = len(servers)
    server = None
    server_name = args.get('--server') or args.get('-s')

    if slen == 0:
        logger.print_error('[%s]中缺少服务器配置[servers]' % utils.config_filename)
        exit(0)
    elif slen > 1:
        if server_name is None:
            logger.print_error('因为配置了多个服务器，请使用--server参数指定服务器名称')
            exit(0)
        for srv in servers:
            if srv.get('name') == server_name:
                server = srv
                break
    else:
        server = servers[0]

    if server is None:
        logger.print_error('未找到服务器配置信息')
        exit(0)
    return server


def handle_post_upload(localbase_path: str):
    """执行`post_upload`配置命令"""
    config: dict = utils.get_config(localbase_path)
    server: dict
    for server in utils.get_servers(config):
        if not server.get('enable', True):
            continue
        command = server.get('post_upload')
        if command is not None:
            host: str = server.get('host')
            port: int = server.get('port')
            username: str = server.get('username')
            password: str = server.get('password')
            logger.print_info('[%s:%s]> %s' % (host, port, command))
            ssh_client = ssh.SSHClient(host, port, username, password)
            ssh_client.exec_command(command)
            ssh_client.close()


def exec_command(localbase_path: str, args: dict):
    """ 执行远程命令 """
    config = utils.get_config(localbase_path)
    server = get_destination_server(config, args)
    command = args.get('--cmd') or args.get('-c')
    ssh_client = ssh.SSHClient(server.get('host'), server.get('port'), server.get('username'), server.get('password'))
    ssh_client.exec_command(command)
    ssh_client.close()


def connect_ssh(localbase_path, args):
    """ 连接到SSH服务 """
    config = utils.get_config(localbase_path)
    server = get_destination_server(config, args)
    terminal = SSHTerminal(server.get('host'), server.get('port'), server.get('username'), server.get('password'))
    try:
        terminal.cmdloop()
    except KeyboardInterrupt:
        pass


def handle_server_command():
    server_list = utils.get_local_server_list()
    if len(server_list) == 0:
        print('没有配置服务器信息')
        return

    print('   %-21s\t%-21s\t%s' % ('服务器地址', '名称', '描述'))
    print(' -----------------------------------------------------------')
    for idx, it in enumerate(server_list):
        host = it.get('host')
        port = str(it.get('port'))
        name = it.get('name')
        desc = it.get('desc')
        print(' %d. %-21s\t%-21s\t%s' % (idx + 1, host + ':' + port, name, desc))


def run():
    args = utils.parse_cmd_args()
    # print(args)
    # return
    # 本地项目根目录
    local_basepath = args.get('--path').replace('\\', '/')
    if not local_basepath.endswith('/'):
        local_basepath += '/'

    action = args.get('--action', 'help') or 'help'
    actions = action.split('/')
    # 版本参数
    version = args.get('--version') or args.get('-v') or ''
    # 是否含全部参数
    has_all = '--all' in args or '-a' in args
    # 配置文件名称
    config_filename = args.get('--file') or args.get('-f')

    switches = {
        'init': lambda: utils.init_config(local_basepath),
        'up': lambda: upload.Upload(local_basepath, version=version, config_filename=config_filename).start(),
        'post': lambda: handle_post_upload(local_basepath),
        'clean': lambda: caches.clean(local_basepath, version, has_all),
        'clean-all': caches.clean_all,
        'bak': lambda: print('远程备份，未实现'),
        'restart-server': lambda: print('重启远程服务器，未实现'),
        'exec': lambda: exec_command(local_basepath, args),
        'connect': lambda: connect_ssh(local_basepath, args),
        'server': handle_server_command,
        'help': show_help,
    }

    for act in actions:
        func = switches.get(act)
        func() if func is not None else show_help()


if __name__ == '__main__':
    run()
